home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / CollationElementIterator.java < prev    next >
Text File  |  1998-09-22  |  12KB  |  341 lines

  1. /*
  2.  * @(#)CollationElementIterator.java    1.15 97/12/05
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.text;
  32.  
  33. import java.lang.Character;
  34. import java.util.Vector;
  35.  
  36. /**
  37.  * The <code>CollationElementIterator</code> class is used as an iterator
  38.  * to walk through each character of an international string. Use the iterator
  39.  * to return the ordering priority of the positioned character. The ordering
  40.  * priority of a character, which we refer to as a key, defines how a character
  41.  * is collated in the given collation object.
  42.  *
  43.  * <p>
  44.  * For example, consider the following in Spanish:
  45.  * <blockquote>
  46.  * <pre>
  47.  * "ca" -> the first key is key('c') and second key is key('a').
  48.  * "cha" -> the first key is key('ch') and second key is key('a').
  49.  * </pre>
  50.  * </blockquote>
  51.  * And in German,
  52.  * <blockquote>
  53.  * <pre>
  54.  * "\u00e4b"-> the first key is key('a'), the second key is key('e'), and
  55.  * the third key is key('b').
  56.  * </pre>
  57.  * </blockquote>
  58.  * The key of a character is an integer composed of primary order(short),
  59.  * secondary order(byte), and tertiary order(byte). Java strictly defines
  60.  * the size and signedness of its primitive data types. Therefore, the static
  61.  * functions <code>primaryOrder</code>, <code>secondaryOrder</code>, and
  62.  * <code>tertiaryOrder</code> return <code>int</code>, <code>short</code>,
  63.  * and <code>short</code> respectively to ensure the correctness of the key
  64.  * value.
  65.  *
  66.  * <p>
  67.  * Example of the iterator usage,
  68.  * <blockquote>
  69.  * <pre>
  70.  * // get the first key of the string
  71.  * String str = "This is a test";
  72.  * CollationElementIterator c =
  73.  *     new CollationElementIterator(str, 0, str.length(),
  74.  *                                  Collator.getInstance());
  75.  * int primaryOrder = CollationElementIterator.primaryOrder(c->next());
  76.  * </pre>
  77.  * </blockquote>
  78.  *
  79.  * <p>
  80.  * <code>CollationElementIterator.next</code> returns the collation order
  81.  * of the next character. A collation order consists of primary order,
  82.  * secondary order and tertiary order. The data type of the collation
  83.  * order is <strong>int</strong>. The first 16 bits of a collation order
  84.  * is its primary order; the next 8 bits is the secondary order and the
  85.  * last 8 bits is the tertiary order.
  86.  *
  87.  * @see                Collator
  88.  * @see                RuleBasedCollator
  89.  * @version            1.15 12/05/97
  90.  * @author             Helena Shih
  91.  */
  92. public final class CollationElementIterator
  93. {
  94.     /**
  95.      * Null order which indicates the end of string is reached by the
  96.      * cursor.
  97.      */
  98.     public final static int NULLORDER = 0xffffffff;
  99.     /**
  100.      * CollationElementIterator constructor.  This takes the source string and
  101.      * the collation object.  The cursor will walk thru the source string based
  102.      * on the predefined collation rules.  If the source string is empty,
  103.      * NULLORDER will be returned on the calls to next().
  104.      * @param sourceText the source string.
  105.      * @param order the collation object.
  106.      */
  107.     CollationElementIterator(String sourceText, RuleBasedCollator order) {
  108.         ordering = order;
  109.         if ( sourceText.length() != 0 ) {
  110.             text = new DecompositionIterator(sourceText, 0,
  111.                                              sourceText.length(),
  112.                                              order.getDecomposition());
  113.         }
  114.     }
  115.     /**
  116.      * Resets the cursor to the beginning of the string.
  117.      */
  118.     public void reset()
  119.     {
  120.         if (text != null)
  121.             text.reset();
  122.         buffer = null;
  123.         expIndex = 0;
  124.         swapOrder = 0;
  125.         text.setDecomposition(ordering.getDecomposition());
  126.     }
  127.  
  128.     /**
  129.      * Get the ordering priority of the next character in the string.
  130.      * @return the next character's ordering.  Returns NULLORDER if
  131.      * the end of string is reached.
  132.      */
  133.     public int next()
  134.     {
  135.         if (text == null)
  136.             return NULLORDER;
  137.         if (text.getDecomposition() != ordering.getDecomposition())
  138.             text.setDecomposition(ordering.getDecomposition());
  139.         if (buffer != null)
  140.         {
  141.             if (expIndex < buffer.length)
  142.             {
  143.                 return strengthOrder(buffer[expIndex++]);
  144.             }
  145.             else
  146.             {
  147.                 buffer = null;
  148.                 expIndex = 0;
  149.             }
  150.         } else if (swapOrder != 0) {
  151.             int order = swapOrder << 16;
  152.             swapOrder = 0;
  153.             return order;
  154.         }
  155.         char ch = text.next();
  156.         if (ch == DecompositionIterator.NULLORDER) {
  157.             return NULLORDER;
  158.         }
  159.  
  160.         int value = ordering.getUnicodeOrder(ch);
  161.         if (value == RuleBasedCollator.UNMAPPED)
  162.         {
  163.             swapOrder = ch;
  164.             return UNMAPPEDCHARVALUE;
  165.         }
  166.         else if (value < RuleBasedCollator.CHARINDEX)
  167.         {
  168.             return strengthOrder(value);
  169.         }
  170.         // contract characters
  171.         else if (value >= RuleBasedCollator.CONTRACTCHARINDEX)
  172.         {
  173.             return strengthOrder(nextContractChar(ch));
  174.         }
  175.         else if (value >= RuleBasedCollator.EXPANDCHARINDEX)
  176.         {
  177.             buffer = ordering.getExpandValueList(ch);
  178.             expIndex = 0;
  179.             return strengthOrder(buffer[expIndex++]);
  180.         }
  181.         return NULLORDER;
  182.     }
  183.     /**
  184.      * Get the primary order of a collation order.
  185.      * @param order the collation order
  186.      * @return the primary order of a collation order.
  187.      */
  188.     public final static int primaryOrder(int order)
  189.     {
  190.         order &= RuleBasedCollator.PRIMARYORDERMASK;
  191.         return (order >>> RuleBasedCollator.PRIMARYORDERSHIFT);
  192.     }
  193.     /**
  194.      * Get the secondary order of a collation order.
  195.      * @param order the collation order
  196.      * @return the secondary order of a collation order.
  197.      */
  198.     public final static short secondaryOrder(int order)
  199.     {
  200.         order = order & RuleBasedCollator.SECONDARYORDERMASK;
  201.         return ((short)(order >> RuleBasedCollator.SECONDARYORDERSHIFT));
  202.     }
  203.     /**
  204.      * Get the tertiary order of a collation order.
  205.      * @param order the collation order
  206.      * @return the tertiary order of a collation order.
  207.      */
  208.     public final static short tertiaryOrder(int order)
  209.     {
  210.         return ((short)(order &= RuleBasedCollator.TERTIARYORDERMASK));
  211.     }
  212.     // ============================================================
  213.     // package private (These need to be made public for searching)
  214.     // ============================================================
  215.     /**
  216.      *  Check if a comparison order is ignorable.
  217.      *  @return true if a character is ignorable, false otherwise.
  218.      */
  219.     final static boolean isIgnorable(int order)
  220.     {
  221.         return ((primaryOrder(order) == 0) ? true : false);
  222.     }
  223.  
  224.     /**
  225.      *  Get the comparison order in the desired strength.  Ignore the other
  226.      *  differences.
  227.      *  @param order The order value
  228.      */
  229.     final int strengthOrder(int order)
  230.     {
  231.         int s = ordering.getStrength();
  232.         if (s == Collator.PRIMARY)
  233.         {
  234.             order &= RuleBasedCollator.PRIMARYDIFFERENCEONLY;
  235.         } else if (s == Collator.SECONDARY)
  236.         {
  237.             order &= RuleBasedCollator.SECONDARYDIFFERENCEONLY;
  238.         }
  239.         return order;
  240.     }
  241.  
  242.     /**
  243.      *  Set the current offset of the character in the processed source string.
  244.      *  @param newOffset The new offset of the accessed character
  245.      */
  246.     final void setOffset(int newOffset)
  247.     {
  248.         if (text != null)
  249.             text.setOffset(newOffset);
  250.     }
  251.  
  252.     /**
  253.      *  Get the current offset of the character in the processed source string.
  254.      *  @return The offset of the accessed character
  255.      */
  256.     final int getOffset()
  257.     {
  258.         if (text != null)
  259.             return text.getOffset();
  260.         return 0;
  261.     }
  262.     /**
  263.      * Set the iterator string.
  264.      * @param source the new string.
  265.      */
  266.     void setText(String source)
  267.     {
  268.         buffer = null;
  269.         swapOrder = 0;
  270.         if (text == null) {
  271.             text = new DecompositionIterator(source, ordering.getDecomposition());
  272.         } else {
  273.             text.setDecomposition(ordering.getDecomposition());
  274.             text.setText(source);
  275.         }
  276.     }
  277.  
  278.     //============================================================
  279.     // privates
  280.     //============================================================
  281.     private int getEntry(Vector list, String name) {
  282.         for (int i = 0; i < list.size(); i++) {
  283.             EntryPair pair = (EntryPair)list.elementAt(i);
  284.             if (pair.entryName.equals(name)) {
  285.                 return i;
  286.             }
  287.         }
  288.         return RuleBasedCollator.UNMAPPED;
  289.     }
  290.  
  291.     /**
  292.      * Get the ordering priority of the next contracting character in the
  293.      * string.
  294.      * @param ch the starting character of a contracting character token
  295.      * @return the next contracting character's ordering.  Returns NULLORDER
  296.      * if the end of string is reached.
  297.      */
  298.     private int nextContractChar(char ch)
  299.     {
  300.         EntryPair pair = null;
  301.         Vector list = ordering.getContractValues(ch);
  302.         int intValue = 0;
  303.         key.setLength(0);
  304.         key.append(ch);
  305.         int n = 0;
  306.         if ((n = getEntry(list, key.toString())) != RuleBasedCollator.UNMAPPED) {
  307.             pair = (EntryPair)list.elementAt(n);
  308.             intValue = pair.value;
  309.         }
  310.         while((ch = text.next()) != DecompositionIterator.NULLORDER)
  311.         {
  312.             key.append(ch);
  313.             if ((n = getEntry(list, key.toString())) ==
  314.                      RuleBasedCollator.UNMAPPED) {
  315.                 ch = text.previous();
  316.                 break;
  317.             }
  318.             pair = (EntryPair)list.elementAt(n);
  319.             intValue = pair.value;
  320.         }
  321.         // if contracting char is also an expanding char
  322.         if ((intValue  - RuleBasedCollator.EXPANDCHARINDEX) >= 0)
  323.         {
  324.             buffer = ordering.getExpandValueList
  325.                      (intValue - RuleBasedCollator.EXPANDCHARINDEX);
  326.             expIndex = 0;
  327.             intValue = buffer[expIndex++];
  328.         }
  329.         return intValue;
  330.     }
  331.  
  332.     final static int UNMAPPEDCHARVALUE = 0x7FFF0000;
  333.  
  334.     private DecompositionIterator text = null;
  335.     private int[] buffer = null;
  336.     private int expIndex = 0;
  337.     private StringBuffer key = new StringBuffer(5);
  338.     private int swapOrder = 0;
  339.     private RuleBasedCollator ordering;
  340. }
  341.